package test
import(
	"reflect"
	"strconv"
	"strings"
	"fmt"
	"encoding/json"
	"log"
	"io/ioutil"
	"net/http"
	"io"
	"os"
	"regexp"
	"time"
)

var DestroyChan = make(chan string,2)

func ShowMemory(x *int){
	fmt.Println("============before================")
	fmt.Println(*x)
	fmt.Println(x)
	fmt.Println("============after================")
	var f int  = 7
	*x = *(&f)
	fmt.Println(*x)
	fmt.Println(x)
	return;
}

func addition(x int,y int) (string,int){
	return "addition result",x+y
}

func deferTest1(){
	fmt.Println("defer test 1")
}
func deferTest2(){
	fmt.Println("defer test 2")
}
func deferTest3(){
	fmt.Println("defer test 3")
}

func argsNumber(numbers...int)int{
	defer deferTest1()
	defer deferTest2()
	defer deferTest3()
	fmt.Println(numbers)
	total :=0
	for _,number:=range numbers{
		total+=number
	}
	return total
}

type Student struct{
	Name string
	Age int
}

func Test(){
	var s string = "false"
	b,err := strconv.ParseBool(s)
	fmt.Println(reflect.TypeOf(b))
	fmt.Println(reflect.TypeOf(err))
	fmt.Println(b)
	fmt.Println("============================")
	var s2 bool = true
	b2 := strconv.FormatBool(s2)
	fmt.Println(reflect.TypeOf(b2))
	fmt.Println(b2)
	fmt.Println("===========ShowMemory=================")
	var i int = 5
	ShowMemory(&i)
	fmt.Println("===========addition=================")
	var x,y int = 5,6

	var (
		result string
		value int
	)
	result,value=addition(x,y)
	fmt.Println(result)
	fmt.Println(value)
	
	fmt.Println("===========argsNumber=================")
	
	fmt.Println(argsNumber(11,22,33))
	fmt.Println("===========if else=================")
	if b{
		fmt.Println("parse b true")
	}else if s2{
		fmt.Println("parse s2 true")
	}
	fmt.Println("===========compare=================")
	var compare_1,compare_2,compare_3,compare_4 int = 1,2,2,3
	if compare_1>compare_2 {
		fmt.Println("compare_1>compare_2")
	}
	if compare_3>=compare_2 {
		fmt.Println("compare_3>=compare_2")
	}
	if compare_1<compare_2{
		fmt.Println("compare_1<compare_2")
	}
	if compare_2==compare_1{
		fmt.Println("compare_1==compare_2")
	}
	if compare_2<=compare_1{
		fmt.Println("compare_1<=compare_2")
	}
	if compare_4>compare_1 && compare_4>compare_3 && compare_4>compare_2 {
		fmt.Println("compare_4 bigger than all")
	}
	fmt.Println("===========switch=================")
	var  switch_value int= 3
	switch switch_value{
	case 1:
		fmt.Println("switch_value 1")
	case 2:
		fmt.Println("switch_value 2")
		fmt.Println("switch_value 2")
	case 3:
		fmt.Println("switch_value 3")
		fmt.Println("switch_value 3")
		fmt.Println("switch_value 3")
	default:
		fmt.Println("switch_value default")
	}
	fmt.Println("===========for i=0 i < 10 =================")
	total:=0
	for i:=0;i<10;i++{
		total+=i
	}
	fmt.Println(total)
	fmt.Println("===========for ranges =================")
	nums  :=[]int{1,2,3,4,5,6}
	for i,num := range nums{
		fmt.Print("nums index i:",i," ")
		fmt.Print("nums value num:",num)
		fmt.Println("")
	}
	fmt.Println("===========arrays =================")
	var cheers [2]string 
	cheers[0]="hello"
	cheers[1]="caiwen"
	fmt.Println(cheers[0])
	fmt.Println(cheers[1])
	fmt.Println(cheers)
	fmt.Println("===========make arrays =================")
	var cheers_make = make([]string,2) 
	cheers_make[0]="hello"
	cheers_make[1]="i"
	fmt.Println(cheers_make[0])
	fmt.Println(cheers_make[1])
	fmt.Println(cheers_make)
	cheers_make=append(cheers_make,"miss","you")
	fmt.Println(cheers_make)
	fmt.Println("===========arrays copy=================")
	var copy_arry = make([]string,2)
	cheers_make=append(cheers_make[:2],cheers_make[2:]...)
	fmt.Println(cheers_make)
	copy(copy_arry,cheers_make[2:])
	fmt.Println(copy_arry)
	fmt.Println("===========map=================")
	var players = make(map[string]int)
	players["hello"]=1
	players["world"]=2
	players["you"]=3
	players["are"]=4
	fmt.Println(players)
	fmt.Println(players["you"])
	delete(players,"world")
	fmt.Println(players)
	fmt.Println("===========struct=================")
	stu := Student{"chenge",30}
	fmt.Println("name",stu.Name)
	fmt.Println("age",stu.Age)
	var stu2 Student
	fmt.Println(stu2)
	fmt.Println("===========strings=================")
	s_up:="HaHaHa"
	fmt.Println(strings.ToLower(s_up))
	
}

type Person struct{
	Name string 
	Age int 
}

func TestJson(){
	fmt.Println("===========TestJson=================")
	jsonData := "{\"name\":\"gerge\",\"age\":40}"
	jsonByteData := []byte(jsonData)
	p:=Person{}
	err:=json.Unmarshal(jsonByteData,&p)
	if(err!=nil){
		log.Fatal(err)
	}
	fmt.Printf("%+v\n",p)
}

func helloWorld(w http.ResponseWriter, r *http.Request) {
	if(r.URL.Path!="/"){
		http.NotFound(w,r)
		return
	}
	switch r.Method{
	case "GET":
		for k,v := range r.URL.Query(){
			fmt.Printf("%s: %s",k,v)
		}
	case "POST":
		reqBody,err := ioutil.ReadAll(r.Body)
		if(err!=nil){
			log.Fatal(err)
		}
		fmt.Printf("reqBody:%s",reqBody)
	case "UP":
		w.Header().Set("Method","UP")
	default:
		w.Header().Set("Method","default")
	}
	switch r.Header.Get("Accept"){
	case"application/json":
		w.Header().Set("Content-Type","application/json;charset=utf-8")
		w.Write([]byte("{\"hello\":\"world\"}"))
	case "application/xml":
		w.Header().Set("Content-Type","application/xml;charset=utf-8")
		w.Write([]byte("<?xml version=\"1.0\" encoding=\"utf-8\"?><Message>hello world</Message>"))
	default:
		w.Header().Set("Content-Type","text/plain;charset=utf-8")
		w.Write([]byte("hello world"))
	}
}

func usersHandler(w http.ResponseWriter, r *http.Request){
	w.Write([]byte("users,hello world\n"))
}

func projectsHandler(w http.ResponseWriter, r *http.Request){
	w.Write([]byte("projects,hello world\n"))
}

func destroyHandler(w http.ResponseWriter, r *http.Request){
	switch r.Method{
	case "GET":
		for k,v := range r.URL.Query(){
			if strings.EqualFold("name",k){
				name := r.URL.Query().Get("name")
				fmt.Printf("key equal name: %s\n",name)
				DestroyChan <- name
			}else{
				fmt.Printf("%s: %s\n",k,v)
			}
		}
	case "POST":
		reqBody,err := ioutil.ReadAll(r.Body)
		if(err!=nil){
			log.Fatal(err)
		}
		fmt.Printf("reqBody:%s",reqBody)
	case "UP":
		w.Header().Set("Method","UP")
	default:
		w.Header().Set("Method","default")
	}
	switch r.Header.Get("Accept"){
	case"application/json":
		w.Header().Set("Content-Type","application/json;charset=utf-8")
		w.Write([]byte("{\"hello\":\"world\"}"))
	case "application/xml":
		w.Header().Set("Content-Type","application/xml;charset=utf-8")
		w.Write([]byte("<?xml version=\"1.0\" encoding=\"utf-8\"?><Message>hello world</Message>"))
	default:
		w.Header().Set("Content-Type","text/plain;charset=utf-8")
		w.Write([]byte("hello world"))
	}
}

func TestHttp(){
	http.HandleFunc("/",helloWorld)
	http.HandleFunc("/destroy/",destroyHandler)
	http.HandleFunc("/users/",usersHandler)
	http.HandleFunc("/projects/",projectsHandler)
	http.ListenAndServe(":8000",nil)
}

func readFile(name string){
	fileBytes,err:=ioutil.ReadFile(name)
	if(err!=nil){
		log.Fatal(err)
	}
	fileString := string(fileBytes)
	fmt.Println("string:",fileString)
}

func writeFile(name string){
	s:="hello world"
	err:=ioutil.WriteFile(name,[]byte(s),0666)
	if(err!=nil){
		log.Fatal(err)
	}
}

func listFiles(){
	files,err:=ioutil.ReadDir(".")
	if err!=nil{
		log.Fatal(err)
	}
	for _,file := range files{
		fmt.Println(file.Mode(),file.Name())
	}
}

func copyFile(){
	from,err := os.Open("./test/read.txt")
	if(err!=nil){
		log.Fatal(err)
	}
	defer from.Close()

	to,err2 := os.OpenFile("./test/copy.txt",os.O_RDWR|os.O_CREATE,0666)
	if(err2!=nil){
		log.Fatal(err2)
	}
	defer to.Close()
	_,err3:=io.Copy(to,from)
	if(err3!=nil){
		log.Fatal(err3)
	}
}

func removeFile(){
	os.Remove("./test/copy.txt")
	os.Remove("./test/write.txt")
}

func TestFileOperate(){
	readFile("./test/read.txt")
	writeFile("./test/write.txt")
	copyFile()
	removeFile()
	listFiles()
}

type config struct{
	Name string
	Awake bool
	Hungry bool
}

func TestConfig(){
	fileBytes,err:=ioutil.ReadFile("./config/config.json")
	if(err!=nil){
		log.Fatal(err)
	}
	c := config{}
	err = json.Unmarshal(fileBytes,&c)
	if(err!=nil){
		log.Fatal(err)
	}
	fmt.Printf("%+v\n",c)
}

func testRegex1(){
	needle := "chocolate"
	hayStack := "Chocolate is delicious!"
	match,err := regexp.MatchString(needle,hayStack)
	if err !=nil {
		log.Fatal(err)
	}
	fmt.Println("match:",match)
}

func testRegex2(){
	needle := "(?i)chocolate"
	hayStack := "Chocolate is delicious!"
	match,err := regexp.MatchString(needle,hayStack)
	if err !=nil {
		log.Fatal(err)
	}
	fmt.Println("match:",match)
}

func regCompare(){
	re := regexp.MustCompile("^[a-zA-Z0-9]{5,12}$")
	fmt.Println(re.MatchString("dajshe32578"))
	fmt.Println(re.MatchString("fdas"))
	fmt.Println(re.MatchString("fda12!s"))
}

func TestRegexp(){
	testRegex1()
	testRegex2()
	regCompare()
}

func TestTimeTick(){
	c :=time.Tick(5*time.Second)
	i := 0
	for t := range c{
		fmt.Printf("the time is now :%v\n",t)
		i=i+1
		if i > 10{
			break
		}
	}
	fmt.Println("TestTimeTick out")
}